package com.jdone.compus.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jdone.compus.dto.ApiResponse;
import com.jdone.compus.dto.PaymentProperties;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.*;

@Service
public class OrderReconciliationService {
    private final Logger logger = LoggerFactory.getLogger(OrderReconciliationService.class);
    private final RestTemplate restTemplate;
    private final PaymentProperties paymentProperties;
    private final OrderRecordService orderRecordService;
    private final ObjectMapper objectMapper = new ObjectMapper();

    public OrderReconciliationService(RestTemplate restTemplate,
                                      PaymentProperties paymentProperties,
                                      OrderRecordService orderRecordService) {
        this.restTemplate = restTemplate;
        this.paymentProperties = paymentProperties;
        this.orderRecordService = orderRecordService;
    }

    public ApiResponse reconcileAndSync(String startTime, String endTime, Integer pageSize, Boolean isUpload) {
        try {
            if (pageSize == null || pageSize <= 0) pageSize = 200;
            int pageNum = 1;
            List<String> errorList = new ArrayList<>();

            String baseUrl = paymentProperties.getUrl();
            if (baseUrl == null || baseUrl.trim().isEmpty()) {
                return new ApiResponse(500, false, "payment.platform.url 未配置", null);
            }
            String queryUrl = baseUrl.endsWith("/") ? baseUrl + "golivepay/order/queryOrder" : baseUrl + "/golivepay/order/queryOrder";

            while (true) {
                Map<String, Object> req = new HashMap<>();
                req.put("myapp_id", paymentProperties.getMyappId());
                req.put("time_stamp", String.valueOf(System.currentTimeMillis()));
                req.put("nonce_str", UUID.randomUUID().toString().replace("-", ""));
                req.put("start_time", startTime);
                req.put("end_time", endTime);
                req.put("pageNum", pageNum);
                req.put("pageSize", pageSize);

                String sign = generateSign(req, paymentProperties.getApiKey());
                req.put("sign", sign);

                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                HttpEntity<Map<String, Object>> entity = new HttpEntity<>(req, headers);

                ResponseEntity<String> resp = restTemplate.postForEntity(queryUrl, entity, String.class);
                if (resp.getStatusCode() != HttpStatus.OK) {
                    String msg = "调用第三方支付平台失败，HTTP=" + resp.getStatusCodeValue();
                    logger.error(msg);
                    return new ApiResponse(500, false, msg, null);
                }

                JsonNode root = objectMapper.readTree(resp.getBody());
                int status = root.path("status").asInt(-1);
                if (status != 200) {
                    String msg = root.path("msg").asText();
                    logger.error("第三方返回非 200：{}", msg);
                    return new ApiResponse(status, false, "第三方返回异常: " + msg, null);
                }

                JsonNode data = root.path("data");
                JsonNode orderEntity = data.path("orderEntity");
                if (!orderEntity.isArray() || orderEntity.size() == 0) {
                    break;
                }

                for (JsonNode orderNode : orderEntity) {
                    try {
                        // 调用独立事务的单条处理
                        orderRecordService.processSingleOrder(orderNode,isUpload);
                        // 注意：processSingleOrder 内部保存/更新，外层这里无法直接知道是 created 还是 updated
                        // 若需要统计 created/updated，可让 processSingleOrder 返回一个 enum/flag 或抛出特定结果
                    } catch (Exception ex) {
                        // 只记录错误信息，继续处理下一条（单条事务已回滚）
                        String err = "处理远端订单异常: " + ex.getMessage() + " | node=" + orderNode.toString();
                        logger.error(err, ex);
                        errorList.add(err);
                    }
                }

                if (orderEntity.size() < pageSize) break;
                pageNum++;
            }

            Map<String, Object> result = new HashMap<>();
            result.put("errors", errorList);
            return new ApiResponse(200, true, "对账完成（详情见 errors）", result);

        } catch (Exception e) {
            logger.error("对账整体异常", e);
            return new ApiResponse(500, false, "对账异常: " + e.getMessage(), null);
        }
    }

    private String generateSign(Map<String, Object> params, String apiKey) {
        SortedMap<String, String> map = new TreeMap<>();
        for (Map.Entry<String, Object> e : params.entrySet()) {
            String k = e.getKey();
            if (k == null) continue;
            if ("sign".equalsIgnoreCase(k)) continue;
            Object v = e.getValue();
            if (v == null) continue;
            String s = String.valueOf(v).trim();
            if (s.isEmpty()) continue;
            map.put(k, s);
        }
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> e : map.entrySet()) {
            sb.append(e.getKey()).append("=").append(e.getValue()).append("&");
        }
        sb.append("key=").append(apiKey == null ? "" : apiKey);
        return DigestUtils.md5Hex(sb.toString()).toUpperCase();
    }
}
